package action

import (
	"fmt"
	"github.com/Ming0706/gorm/internal"
	"github.com/jinzhu/gorm"
	"time"
)

func Update() {
	// 其余更新操作举例
	// 这个更新操作只使用了 WHERE 条件，没有在 Model 中指定 id
	// update user set name='卢友明' where age=22;
	if err := internal.DB.Model(&internal.User{}).Where("AGE = ?", 22).
		Update("name", "卢友明").Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// 多个条件写法：update user set name='李欣伟' where age=22 and name='卢友明';
	if err := internal.DB.Model(&internal.User{}).Where("age = ?", 22).Where("name = ?", "卢友明").
		Update("name", "李欣伟").Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// update user set name='卢友明' where id=2;
	if err := internal.DB.Model(&internal.User{}).Where("id = ?", 2).
		Update("name", "卢友明").Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// update user set name='卢友明', age=23;
	// 使用 map 更新多个属性，只会更新 map 中存在的属性
	//if err := internal.DB.Model(&internal.User{}).
	//	Update(map[string]interface{}{"name": "卢友明", "age": 23}).Error; err != nil {
	//	fmt.Printf("更新数据错误！\nError: %v\n", err)
	//}

	// 更新选定字段
	// 定义需要更新的结构体
	user := User{
		Id:         2,
		Name:       "卢友明",
		Age:        23,
		CreateTime: time.Now(),
	}
	// 更新时不对 name 字段进行更改
	// update user set age=23, create_time=now() where id = 2;
	if err := internal.DB.Model(&User{}).Omit("name").
		Update(&user).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// 只对 name 字段进行更改
	// update user set name='卢友明';  注：改全表
	//if err := internal.DB.Model(&User{}).Select("name").
	//	Update(&user).Error; err != nil {
	//	fmt.Printf("更新数据错误！\nError: %v\n", err)
	//}

	// 无 Hooks 更新
	// 定义需要更新的结构体
	user = User{Id: 1}
	// 更新单个属性，类似于 `Update`
	// update user set name='卢友明' where id=1;
	if err := internal.DB.Model(&user).
		UpdateColumn("name", "卢友明").Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// 更新多个属性，类似于 `Updates`
	// update user set name='李欣伟', age=18 where id=1;
	if err := internal.DB.Model(&user).
		UpdateColumns(User{Name: "李欣伟", Age: 18}).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}

	// 批量更新
	// update user set name='李欣伟', age=22, where id in(1, 2);
	if err := internal.DB.Table("user").Where("id IN (?)", []int{1, 2}).
		Update(map[string]interface{}{"name": "李欣伟", "age": 22}).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// 使用 structType 更新时，只会更新非零值字段，若想更新所有字段，需使用 map[string]interface{}
	// update user set name='卢友明', age=18;		改全表
	if err := internal.DB.Model(User{}).Update(User{Name: "卢友明", Age: 23}).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// 使用 `RowsAffected` 获取更新记录总数
	updateTotal := internal.DB.Model(User{}).Updates(User{Name: "李欣伟", Age: 18}).RowsAffected
	fmt.Printf("更新的记录量是%v\n", updateTotal)

	// 使用 sql 表达式更新
	// 定义需要更新的结构体
	user = User{Id: 1}
	// 先计算年龄的值再执行更新操作
	// update user set age = age * '2' + '100' where id = 1;
	if err := internal.DB.Model(&user).
		Update("age", gorm.Expr("age * ? + ?", 2, 100)).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// update user set age = age * '2' + '100' where id = 1;
	if err := internal.DB.Model(&user).
		Updates(map[string]interface{}{"age": gorm.Expr("age * ? + ?", 2, 100)}).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// update user set age = age - 10 where id = 1;
	if err := internal.DB.Model(&user).
		UpdateColumn("age", gorm.Expr("age - ?", 10)).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
	// update user set age = age - 10 where id = 1 and age > 12;
	if err := internal.DB.Model(&user).
		Where("age > 12").UpdateColumn("age", gorm.Expr("age - ?", 10)).Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
	}
}

// SaveUser 更新所有字段数据
func (user *User) SaveUser() (err error) {
	// Save 会更新所有字段，即使你没有赋值，没赋值的更新为 0 或 null，且非空属性必须赋值
	// 一般建议使用 internal.DB.Model(&user).Update(user)
	updateDb := internal.DB.Save(&user)

	if err := updateDb.Error; err != nil {
		fmt.Printf("更新数据错误！\nError: %v\n", err)
		return err
	}
	return nil
}
